package com.codepilot.server.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.codepilot.server.model.entity.Problem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.codepilot.server.converter.ProblemConverter;
import com.codepilot.server.mapper.ProblemMapper;
import com.codepilot.server.model.dto.ProblemDTO;
import com.codepilot.server.model.entity.LeecodeProblem;
import com.codepilot.server.model.entity.OpenjudgeProblem;
import com.codepilot.server.model.exception.enums.GlobalErrorCodeConstants;
import com.codepilot.server.model.vo.CommonResult;
import com.codepilot.server.model.vo.ProblemVO;
import com.codepilot.server.service.ProblemService;

@Service
public class ProblemServiceImpl implements ProblemService {

    @Autowired
    private ProblemMapper problemMapper;

    @Override
    public CommonResult<?> getList(String source, int pageNo, int pageSize) {
        int offset = pageNo * pageSize;
        int limit = pageSize;
        List<ProblemVO> result = new ArrayList<>();
        try {
            if (source.equals("LC")) {
                List<LeecodeProblem> leecodeProblems = problemMapper.getLeecodeProblems(offset, limit);
                for (LeecodeProblem leecodeProblem : leecodeProblems) {
                    ProblemDTO problemDTO = ProblemConverter.INSTANCE.leecode2ProblemDTO(leecodeProblem);
                    result.add(ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO));
                }
            } else if (source.equals("OJ")) {
                List<OpenjudgeProblem> openjudgeProblems = problemMapper.getOpenjudgeProblems(offset, limit);
                for (OpenjudgeProblem openjudgeProblem : openjudgeProblems) {
                    ProblemDTO problemDTO = ProblemConverter.INSTANCE.openjudge2ProblemDTO(openjudgeProblem);
                    result.add(ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO));
                }
            }
            return CommonResult.success(result);
        } catch (Exception e) {
            return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public CommonResult<?> searchOne(String source, String title) {
        title = "%" + title + "%";
        try {
            ProblemDTO problemDTO;
            if (source.equals("LC")) {
                LeecodeProblem leecodeProblem = problemMapper.getLeecodeProblemByTitle(title);
                problemDTO = ProblemConverter.INSTANCE.leecode2ProblemDTO(leecodeProblem);
            } else if (source.equals("OJ")) {
                OpenjudgeProblem openjudgeProblem = problemMapper.getOpenjudgeProblemByTitle(title);
                problemDTO = ProblemConverter.INSTANCE.openjudge2ProblemDTO(openjudgeProblem);
            } else {
                return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST);
            }
            ProblemVO problemVO = ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO);
            return CommonResult.success(problemVO);
        } catch (Exception e) {
            return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public CommonResult<?> searchList(String source, String title, int size) {
        title = "%" + title + "%";
        try {
            List<ProblemVO> result = new ArrayList<>();
            if (source.equals("LC")) {
                List<LeecodeProblem> leecodeProblems = problemMapper.getLeecodeProblemsByTitle(title, size);
                for (LeecodeProblem leecodeProblem : leecodeProblems) {
                    ProblemDTO problemDTO = ProblemConverter.INSTANCE.leecode2ProblemDTO(leecodeProblem);
                    result.add(ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO));
                }
            } else if (source.equals("OJ")) {
                List<OpenjudgeProblem> openjudgeProblems = problemMapper.getOpenjudgeProblemsByTitle(title, size);
                for (OpenjudgeProblem openjudgeProblem : openjudgeProblems) {
                    ProblemDTO problemDTO = ProblemConverter.INSTANCE.openjudge2ProblemDTO(openjudgeProblem);
                    result.add(ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO));
                }
            } else {
                return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST);
            }
            return CommonResult.success(result);
        } catch (Exception e) {
            return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public CommonResult<?> getProblemById(String source, int problemId) {
        if (source.equals("LC")) {
            LeecodeProblem leecodeProblem = problemMapper.getLeecodeProblemById(problemId);
            ProblemDTO problemDTO = ProblemConverter.INSTANCE.leecode2ProblemDTO(leecodeProblem);
            return CommonResult.success(ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO));
        } else if (source.equals("OJ")) {
            OpenjudgeProblem openjudgeProblem = problemMapper.getOpenjudgeProblemById(problemId);
            ProblemDTO problemDTO = ProblemConverter.INSTANCE.openjudge2ProblemDTO(openjudgeProblem);
            return CommonResult.success(ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO));
        }
        return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST);
    }

    @Override
    public CommonResult<Integer> getProblemUid(String source, int id) {
        try {
            Integer uid = problemMapper.getProblemUid(source, id);
            return CommonResult.success(uid);
        } catch (Exception e) {
            return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public CommonResult<ProblemVO> getProblemByUid(int uid) {
        try {
            Problem problem = problemMapper.getProblemByUid(uid);
            ProblemDTO problemDTO = null;
            if (problem.getSource().equals("LC")) {
                LeecodeProblem leecodeProblem = problemMapper.getLeecodeProblemById(problem.getSubId());
                problemDTO = ProblemConverter.INSTANCE.leecode2ProblemDTO(leecodeProblem);
            } else if (problem.getSource().equals("OJ")) {
                OpenjudgeProblem openjudgeProblem = problemMapper.getOpenjudgeProblemById(problem.getSubId());
                problemDTO = ProblemConverter.INSTANCE.openjudge2ProblemDTO(openjudgeProblem);
            }
            ProblemVO problemVO = ProblemConverter.INSTANCE.problemDTO2ProblemVO(problemDTO);
            return CommonResult.success(problemVO);
        } catch (Exception e) {
            return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
    }

}
